Skip to content

feat(permission): add harness-owned worker grant envelope - #1222

Open
TheGreatAxios wants to merge 7 commits into
mainfrom
cl-9475-worker-grant
Open

TheGreatAxios wants to merge 7 commits into
mainfrom
cl-9475-worker-grant

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • A worker deny-on-ask registers a harness-owned denied-call envelope carrying the exact denied ToolCall plus a stable path-aware fingerprint, keyed by worker session with a ten-minute wall-clock TTL
  • The deny reason names only the envelope requestId; the worker binds its ask to that denial via grant_request_id, and the parent replays the exact call through its own gate operator path before retrying via the existing resume_agent
  • Authorize leaves the envelope pending and the execution backstop spends it, so one grant permits exactly one execution across both production stages; replays, tampered args/cwd/tool, foreign ids, or interrupt fail closed with a truthful blocker, sibling sessions fall through to their own round, and expiry yields a fresh gate round while concurrent identical executions serialize to exactly-once

Verification

  • bun run check passes: lint, typecheck, dead-export guard, build, and the guarded test suite (7587 pass, 0 fail across 513 files)
  • New coverage: envelope lifecycle, deny-grant-one-retry flow, send_input grants nothing, race serialization, envelope reuse across reactor retries, grant_request_id threading, production two-stage authorize-then-execute keeper, per-session envelope keeper (pending and consumed variants), non-matching-id fallback

Review follow-ups

  • Blocker 1: authorizeWorkerCallInner no longer consumes on allow; executionVerdictWorkerCallInner is the sole spend point, so the granted retry survives authorize then executes once, and a second execution denies as already consumed
  • Blocker 2: precheck no longer vetoes a session on another session's pending or consumed envelope; each session mints and spends its own envelope through its own grant round, while tampered cwd and foreign grant ids still fail closed
  • NIT 1 (removed, zero production callers): buildRetryMessage, byQuestion, decline/declineAllForSession (+ the declined status), auditTrail, and the onDeniedCall hook; audit history remains readable on the envelope itself
  • NIT 2: registerAsk passes the session-store clock into attachToAsk, so grant timestamps respect fake timers

Fixes CL-9475

@linear-code

linear-code Bot commented Sep 29, 2026

Copy link
Copy Markdown

CL-9475

A worker deny-on-ask registers a denied-call envelope keyed by worker
session with single-parent-turn expiry. The deny reason names only the
envelope requestId and the parent retries via resume_agent with exact
args.
Ask names its denial via grant_request_id; unnamed keeps
first-pending. Expiry yields a fresh gate round that mints a fresh
envelope. Precheck-to-consume serializes per fingerprint.
origin/main relocated shared test helpers from tests/helpers to
testkit; the grant threading test follows the mock-module import.
Two denies of the same exact call under fresh call ids name the same
grant request instead of prompting the parent twice.
Authorize leaves the envelope pending so the granted retry survives the
execution backstop, which now spends it exactly once; precheck no longer
vetoes sibling sessions, and unwired helpers are removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant